VA 是絕對位置
RVA 是由基準位置後的相對位置
並且可以這樣換算 : VA + ImageBase = RVA
而 PE Header 中通常以 RVA 標記位置訊息。
PE檔解析
我們先上一份看起來很簡單的表

這四個區塊代表著在 PE 檔中的內容分區。而不同的區塊有不同功能,存放各自任務需要的資料。
DOS Header : 開頭有一個校驗碼。在 windows NT 架構中大多數欄位用不到了,但是裡面有放 NT Header 的起點位置偏移量 ( 工具人的概念 )。NT Header : 開頭也有一個校驗碼。可以再分成 File header 跟 Optional header,裡面放著要裝載程式所需要的準備與檔案資料。Section Header : 標示出 DATA 部分的資訊,讓編譯器可以知道資料有幾個區塊與資料的位置在哪裡。Section Data : 這邊放著我們寫的資料,像是 .text .data .idata 等等的。好,現在讓這表現出原形。

雖然看起來很複雜,但不過就是上面那幾個區塊的內容,我們來看這些區塊的內容有甚麼含意。
這個部分一開始會有一個校驗碼 ( Magic number ) ,一定會是 4D 5A 00 00 ( M Z 0 0 )。
然後中間這些不用管,那個現在不重要。

其實 Windows NT 之前 Win 是基於 DOS系統,為了向前兼容所以才保留這個格式。
然後在 0x3C 的位置有標示 NT Header 的位置( RVA ),依據這個位置就可以找到 NT Header。
看看在 winnt.h 中這個結構長甚麼樣

裡面的 e_magic 是校驗碼,e_lfanew 是 NT Header 的 RVA(文件偏移)同時也是 FOA(檔案位置) ,要記起來。
這個部分一開始也會有一個校驗碼,一定會是 50 45 00 00 ( P E 0 0 )。

裡面三個物件 : 校驗碼、FileHeader、OptionalHeader。
這個部分在生成 COFF 檔案時就出現了,記錄編譯時的訊息。

其中這些的意思 :
Machine 機械碼類型,像我是 8664 對應 AMD64
NumberOfSections 代表 Section 中有幾個塊狀區塊
TimeDateStamp 編譯時的時間
SizeOfOptionalHeader 就是 OptionHeader 的大小
Characteristics 紀錄 PE 模組屬性,可以透過 value 來得知意義

包含連接器補上的紀錄資訊,使 application loader 可以正確裝載程式

有夠長,列出重要的部分 :
ImageBase : PE model 應該要被寫在哪個位置上
Size of Image : 這程式要申請多大的記憶體
SizeOfHeaders : [DOS + NT + Selection] header 有多大
AddressOfEntryPoint : 程式進入點,也就是 EP,很重要
SectionAlignment : 動態區段對齊大小
FileAlignment : 靜態區段對齊大小
DataDirectory : 這是一個 list , 紀錄 15 種可能需要的資料的起始與大小。
附上他的結構

NT Header 到這邊結束,接下來是 Section。
在編譯時編譯器把程式碼轉成很多塊,為了記錄這些塊狀資料的資訊所以有了 Section Header。

看起來很容易理解。首先可以看到很多個區塊,這些區塊的數量在 NT Header -> FileHeader . NumberOfSections 可以得到。
PointerToRawData : 這個 Block 在靜態檔案的偏移量
SizeOfRawData : Block 所使用的空間
VirtualAddress : 寫入 Image base 的偏移量,也就是 page 中的 Offset。
VirtualSize : 動態空間所需要分配的空間
Characteristics : 紀錄空間在編譯時該區段的使用權限 ( 讀 / 寫 / 執行 )。
